﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Caliburn.Micro;
using OsmerFvg.Resources;
using Windows.Phone.Speech.Synthesis;

namespace OsmerFvg.ViewModels
{
    public class MainPageViewModel : Conductor<IScreen>.Collection.OneActive
    {
        public enum Pages
        {
            Today,
            Tomorrow,
            TomorrowAfter
        }

        private readonly INavigationService _navigationService;

        public string voiceCommandName { get; set; }

        protected override void OnInitialize()
        {
            base.OnInitialize();
            RegisterVoiceCommands();
        }

        protected override async void OnActivate()
        {
            base.OnActivate();

            if (DesignerProperties.IsInDesignTool)
                return;

            await DownloadDescriptions();

            if (!string.IsNullOrEmpty(voiceCommandName))
            {
                ProcessVoiceCommand(voiceCommandName);
                voiceCommandName = string.Empty;
            }

        }

        public MainPageViewModel(INavigationService navigationService)
        {

            _navigationService = navigationService;

        }

        #region Voice Command Management

        private void ProcessVoiceCommand(string voiceCommand)
        {
            switch (voiceCommand)
            {
                case "ReadTodayForecast":
                    ReadForecast(Pages.Today);
                    break;
                case "ReadTomorrowForecast":
                    ReadForecast(Pages.Tomorrow);
                    break;
                case "ReadTomorrowAfterForecast":
                    ReadForecast(Pages.TomorrowAfter);
                    break;
            }
        }

        private static async void RegisterVoiceCommands()
        {
            try
            {
                var uri = new Uri("ms-appx:///VoiceCommands.xml", UriKind.Absolute);
                await Windows.Phone.Speech.VoiceCommands.VoiceCommandService.InstallCommandSetsFromFileAsync(uri);
            }
            catch (Exception error)
            {
                MessageBox.Show(error.Message + "\r\nComandi vocali non impostati.");
            }
        }

        private async void ReadForecast(Pages page)
        {
            IsNotReading = false;
            var synth = new SpeechSynthesizer();
            switch (page)
            {
                case Pages.Today:
                    await synth.SpeakTextAsync(TodayForecast);
                    break;
                case Pages.Tomorrow:
                    await synth.SpeakTextAsync(TomorrowForecast);
                    break;
                case Pages.TomorrowAfter:
                    await synth.SpeakTextAsync(TomorrowAfterForecast);
                    break;
            }
            IsNotReading = true;

        }

        #endregion


        #region Load Descriptions

        private async Task DownloadDescriptions()
        {

            var t1 = DownloadDescription(Pages.Today);
            var t2 = DownloadDescription(Pages.Tomorrow);
            var t3 = DownloadDescription(Pages.TomorrowAfter);

            await Task.WhenAll(new List<Task> {t1, t2, t3});
            
            LoadComplete = true;

        }

        private async Task DownloadDescription(Pages page)
        {

            var urlString = "";

            switch (page)
            {
                case Pages.Today:
                    urlString = AppResources.TodayDescription;
                    break;
                case Pages.Tomorrow:
                    urlString = AppResources.TomorrowDescription;
                    break;
                case Pages.TomorrowAfter:
                    urlString = AppResources.TomorrowAfterDescription;
                    break;
            }

            // Initialize a new web request
            var request = (HttpWebRequest)WebRequest.Create(urlString);

            using (var response = await request.GetResponseAsync())
            using (var source = response.GetResponseStream())
            {
                // Read the response stream
                var streamReader = new StreamReader(source, Encoding.UTF8);
                var sWebPage = streamReader.ReadToEnd();
                streamReader.Close();

                var panoramaItemHeader = GetTitleFromWebPage(sWebPage);
                var forecastHeader = GetHeaderFromWebPage(sWebPage);
                var forecast = GetForecastFromWebPage(sWebPage);

                switch (page)
                {
                    case Pages.Today:
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TodayItem = panoramaItemHeader; });
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TodayHeader = forecastHeader; });
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TodayForecast = forecast; });
                        break;
                    case Pages.Tomorrow:
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TomorrowItem = panoramaItemHeader; });
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TomorrowHeader = forecastHeader; });
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TomorrowForecast = forecast; });
                        break;
                    case Pages.TomorrowAfter:
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TomorrowAfterItem = panoramaItemHeader; });
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TomorrowAfterHeader = forecastHeader; });
                        Deployment.Current.Dispatcher.BeginInvoke(() => { TomorrowAfterForecast = forecast; });
                        break;
                }
            }
        }

        private static string GetTitleFromWebPage(string sWebPage)
        {
            var a = new HtmlAgilityPack.HtmlDocument();
            a.LoadHtml(sWebPage);
            var nodes = a.DocumentNode.ChildNodes[0].ChildNodes[3].ChildNodes[1].ChildNodes[3].ChildNodes[1].ChildNodes[1];
            return HtmlAgilityPack.HtmlEntity.DeEntitize(nodes.ChildNodes[6].InnerText.Trim('\n'));

            //var regionStart = sWebPage.IndexOf("REGIONE:", StringComparison.Ordinal) + "REGIONE:".Length;
            //var regionEnd = sWebPage.IndexOf("previsione", regionStart, StringComparison.Ordinal) - 1;
            //return sWebPage.Substring(regionStart, regionEnd - regionStart + 1).Replace("&igrave;", "ì").Replace("<br>", "").Replace("<BR>", "").Replace("<b>", "").Replace("<B>", "").Replace("</b>", "").Replace("</B>", "").Replace("\n", "");
        }

        private static string GetHeaderFromWebPage(string sWebPage)
        {

            var a = new HtmlAgilityPack.HtmlDocument();
            a.LoadHtml(sWebPage);
            var nodes = a.DocumentNode.ChildNodes[0].ChildNodes[3].ChildNodes[1].ChildNodes[3].ChildNodes[1].ChildNodes[1];
            return HtmlAgilityPack.HtmlEntity.DeEntitize(nodes.ChildNodes[8].InnerText.Trim('\n')) + 
                                                         Environment.NewLine + 
                                                         HtmlAgilityPack.HtmlEntity.DeEntitize(nodes.ChildNodes[10].InnerText.Trim('\n'));

            //var regionStart = sWebPage.IndexOf("previsione", StringComparison.Ordinal);
            //var regionEnd = sWebPage.IndexOf("%", regionStart, StringComparison.Ordinal);
            //if (regionEnd == -1)
            //{
            //    regionEnd = sWebPage.IndexOf("TENDENZA:", regionStart, StringComparison.Ordinal) - 1;
            //}
            //return sWebPage.Substring(regionStart, regionEnd - regionStart + 1).Replace("&agrave;", "à").Replace("<br>", "").Replace("<BR>", "");
        }

        private static string GetForecastFromWebPage(string sWebPage)
        {
            var a = new HtmlAgilityPack.HtmlDocument();
            a.LoadHtml(sWebPage);
            var nodes = a.DocumentNode.ChildNodes[0].ChildNodes[3].ChildNodes[1].ChildNodes[3].ChildNodes[1].ChildNodes[1];
            return HtmlAgilityPack.HtmlEntity.DeEntitize(nodes.ChildNodes[15].InnerText.Trim('\n'));

            //var regionStart = sWebPage.IndexOf("TENDENZA:", StringComparison.Ordinal);
            //if (regionStart == -1)
            //{
            //    regionStart = sWebPage.IndexOf(@"alt=""... caricamento immagine ...""><br>", StringComparison.Ordinal) + @"alt=""... caricamento immagine ...""><br>".Length;
            //}

            //var regionEnd = sWebPage.IndexOf("</td></tr><tr><td><font face=verdana size=1>[*]", regionStart, StringComparison.Ordinal);
            //return sWebPage.Substring(regionStart, regionEnd - regionStart).Replace("&agrave;", "à").Replace("&igrave;", "ì").Replace("&egrave;", "è").Replace("&ugrave;", "ù").Replace("<br>", "").Replace("<BR>", "").Replace("\n", "");
        }

        #endregion

        #region MVVM Properties

        private bool _loadComplete;
        public bool LoadComplete
        {
            get { return _loadComplete; }
            set
            {
                if (_loadComplete != value)
                {
                    _loadComplete = value;
                    NotifyOfPropertyChange(() => LoadComplete);
                }
            }
        }


        private bool _isNotReading = true;
        public bool IsNotReading
        {
            get { return _isNotReading; }
            set
            {
                if (_isNotReading != value)
                {
                    _isNotReading = value;
                    NotifyOfPropertyChange(() => IsNotReading);
                }
            }
        }

        private string _todayItem;
        public string TodayItem
        {
            get { return _todayItem; }
            set
            {
                if (_todayItem != value)
                {
                    _todayItem = value;
                    NotifyOfPropertyChange(() => TodayItem);
                }
            }
        }

        private string _todayHeader;
        public string TodayHeader
        {
            get { return _todayHeader; }
            set
            {
                if (_todayHeader != value)
                {
                    _todayHeader = value;
                    NotifyOfPropertyChange(() => TodayHeader);
                }
            }
        }

        private string _todayForecast;
        public string TodayForecast
        {
            get { return _todayForecast; }
            set
            {
                if (_todayForecast != value)
                {
                    _todayForecast = value;
                    NotifyOfPropertyChange(() => TodayForecast);
                }
            }
        }

        private string _tomorrowItem;
        public string TomorrowItem
        {
            get { return _tomorrowItem; }
            set
            {
                if (_tomorrowItem != value)
                {
                    _tomorrowItem = value;
                    NotifyOfPropertyChange(() => TomorrowItem);
                }
            }
        }

        private string _tomorrowHeader;
        public string TomorrowHeader
        {
            get { return _tomorrowHeader; }
            set
            {
                if (_tomorrowHeader != value)
                {
                    _tomorrowHeader = value;
                    NotifyOfPropertyChange(() => TomorrowHeader);
                }
            }
        }

        private string _tomorrowForecast;
        public string TomorrowForecast
        {
            get { return _tomorrowForecast; }
            set
            {
                if (_tomorrowForecast != value)
                {
                    _tomorrowForecast = value;
                    NotifyOfPropertyChange(() => TomorrowForecast);
                }
            }
        }

        private string _tomorrowAfterItem;
        public string TomorrowAfterItem
        {
            get { return _tomorrowAfterItem; }
            set
            {
                if (_tomorrowAfterItem != value)
                {
                    _tomorrowAfterItem = value;
                    NotifyOfPropertyChange(() => TomorrowAfterItem);
                }
            }
        }

        private string _tomorrowAfterHeader;
        public string TomorrowAfterHeader
        {
            get { return _tomorrowAfterHeader; }
            set
            {
                if (_tomorrowAfterHeader != value)
                {
                    _tomorrowAfterHeader = value;
                    NotifyOfPropertyChange(() => TomorrowAfterHeader);
                }
            }
        }


        private string _tomorrowAfterForecast;
        public string TomorrowAfterForecast
        {
            get { return _tomorrowAfterForecast; }
            set
            {
                if (_tomorrowAfterForecast != value)
                {
                    _tomorrowAfterForecast = value;
                    NotifyOfPropertyChange(() => TomorrowAfterForecast);
                }
            }
        }



        private Uri _todayImageSource = new Uri(AppResources.TodayImageSource, UriKind.Absolute);
        public Uri TodayImageSource
        {
            get { return _todayImageSource; }
            set
            {
                if (_todayImageSource != value)
                {
                    _todayImageSource = value;
                    NotifyOfPropertyChange(() => TodayImageSource);
                }
            }
        }

        private Uri _tomorrowImageSource = new Uri(AppResources.TomorrowImageSource, UriKind.Absolute);
        public Uri TomorrowImageSource
        {
            get { return _tomorrowImageSource; }
            set
            {
                if (_tomorrowImageSource != value)
                {
                    _tomorrowImageSource = value;
                    NotifyOfPropertyChange(() => TomorrowImageSource);
                }
            }
        }

        private Uri _tomorrowAfterImageSource = new Uri(AppResources.TomorrowAfterImageSource, UriKind.Absolute);
        public Uri TomorrowAfterImageSource
        {
            get { return _tomorrowAfterImageSource; }
            set
            {
                if (_tomorrowAfterImageSource != value)
                {
                    _tomorrowAfterImageSource = value;
                    NotifyOfPropertyChange(() => TomorrowAfterImageSource);
                }
            }
        }

        public Uri RadarIconUri
        {
            get { return new Uri(AppResources.RadarIconSource, UriKind.Relative); }
        }

        public Uri WebcamsIconUri
        {
            get { return new Uri(AppResources.WebCamsIconSource, UriKind.Relative); }
        }

        public Uri AboutIconUri
        {
            get { return new Uri(AppResources.AboutIconSource, UriKind.Relative); }
        }

        public Uri ReadForecastIconUri
        {
            get
            {
                return new Uri(AppResources.ReadForecastIconSource, UriKind.Relative);
            }
        }

        #endregion

        #region MVVM Commands

        public void TodayImageTapCommand()
        {
            _navigationService.UriFor<ForecastZoomViewModel>()
                .WithParam(x => x.PageHeaderText, TodayHeader)
                .WithParam(x => x.ForecastImageSource, TodayImageSource)
                .Navigate();
        }


        public void TomorrowImageTapCommand()
        {
            _navigationService.UriFor<ForecastZoomViewModel>()
                .WithParam(x => x.PageHeaderText, TomorrowHeader)
                .WithParam(x => x.ForecastImageSource, TomorrowImageSource)
                .Navigate();
        }


        public void TomorrowAfterImageTapCommand()
        {
            _navigationService.UriFor<ForecastZoomViewModel>()
                .WithParam(x => x.PageHeaderText, TomorrowAfterHeader)
                .WithParam(x => x.ForecastImageSource, TomorrowAfterImageSource)
                .Navigate();
        }

        public void AboutIconClickCommand()
        {
            _navigationService.UriFor<AboutPageViewModel>()
                .Navigate();
        }

        public void RadarIconClickCommand()
        {
            _navigationService.UriFor<RadarPageViewModel>()
                .Navigate();
        }

        public void WebcamsIconClickCommand()
        {
            _navigationService.UriFor<WebCamsViewModel>()
                .Navigate();
        }

        public void ReadForecastClickCommand(int selectedIndex)
        {

            switch (selectedIndex)
            {
                case 0:
                    ReadForecast(Pages.Today);
                    break;
                case 1:
                    ReadForecast(Pages.Tomorrow);
                    break;
                case 2:
                    ReadForecast(Pages.TomorrowAfter);
                    break;
            }
        }

        #endregion

    }

}
